Skip to content

Use scoped bindings for Octane compatibility#509

Merged
arukompas merged 2 commits into
opcodesio:mainfrom
faraweilyas:fix/adjust-container-binding-for-octane-comp
Mar 15, 2026
Merged

Use scoped bindings for Octane compatibility#509
arukompas merged 2 commits into
opcodesio:mainfrom
faraweilyas:fix/adjust-container-binding-for-octane-comp

Conversation

@faraweilyas
Copy link
Copy Markdown
Contributor

This PR updates the service container bindings in LogViewerServiceProvider from bind/singleton to scoped.

Why is this change necessary?

When running Log Viewer in a Laravel Octane environment (FreankenPHP, Swoole, RoadRunner, etc.), the application container persists between requests. Using standard bindings for services like LogViewerService or LogTypeRegistrar can cause issues when using custom resolvers.

Because the resolver logic often depends on the current request state, using scoped ensures that:

  1. The service is fresh for every new incoming request.
  2. The service still acts as a singleton within the lifecycle of that single request (performance efficiency).
  3. Stale data or configuration from a previous request doesn't "leak" into the next one.

Changes

  • Changed log-viewer binding to scoped.
  • Changed log-viewer-cache binding to scoped.
  • Changed LogTypeRegistrar binding to scoped.

References:


Proposed Code Changes

// src/LogViewerServiceProvider.php

-       $this->app->bind('log-viewer', LogViewerService::class);
-       $this->app->bind('log-viewer-cache', function () {
+       $this->app->scoped('log-viewer', LogViewerService::class);
+       $this->app->scoped('log-viewer-cache', function () {
            return Cache::driver(config('log-viewer.cache_driver'));
        });

        if (! $this->app->bound(LogTypeRegistrar::class)) {
-           $this->app->singleton(LogTypeRegistrar::class, function () {
+           $this->app->scoped(LogTypeRegistrar::class, function () {
                return new LogTypeRegistrar;
            });
        }

Octane Use Case / Reproduction

In a Laravel Octane environment, the Application container is booted once and stays in memory. When using a custom host resolver like the one below, standard bind or singleton registrations can cause the LogViewerService to hold onto state from the very first request that initialized it.

/**
 * In a ServiceProvider boot method
 */
public function boot()
{
    // If 'log-viewer' is not scoped, Octane may reuse the service instance
    // across different requests, potentially ignoring runtime changes 
    // or request-specific logic inside this resolver.
    LogViewer::resolveHostsUsing(function (HostCollection $hosts) {
        return [
            'local' => [
                'name' => 'Local logs',
            ],
            'staging' => [
                'name' => 'Staging server',
                'host' => 'https://staging.example.com/log-viewer',
            ],
        ];
    });
}

By switching to $this->app->scoped(), we guarantee that the LogViewerService is re-resolved from the container at the start of every Octane "sandbox" request, while still maintaining singleton-like behavior within the duration of that single request.

@faraweilyas faraweilyas marked this pull request as draft March 12, 2026 16:47
@faraweilyas faraweilyas changed the base branch from 3.x to main March 12, 2026 16:48
@faraweilyas faraweilyas marked this pull request as ready for review March 12, 2026 16:48
@arukompas arukompas merged commit 8afefde into opcodesio:main Mar 15, 2026
57 checks passed
@arukompas
Copy link
Copy Markdown
Contributor

Thanks a lot @faraweilyas ! Tagged new release v3.24.0 - https://github.com/opcodesio/log-viewer/releases/tag/v3.24.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants